package com.test.example.controller.async;

import cn.hutool.extra.spring.SpringUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import static com.xingluo.tools.async.AsyncAutoConfiguration.ASYNC_EXECUTORS;
import static com.xingluo.tools.async.AsyncAutoConfiguration.PRIMARY_EXECUTOR;

@RestController
public class AsyncController {

    @Autowired
    private AsyncService asyncService;

    // 主线程池
    @Resource(name = PRIMARY_EXECUTOR)
    private ThreadPoolTaskExecutor primaryExecutor;

    // 其他线程池
    @Resource(name = ASYNC_EXECUTORS)
    private Map<String, ThreadPoolTaskExecutor> asyncExecutors;


    @GetMapping("/async")
    public String triggerAsync(HttpServletRequest request) {
        // 调用异步方法
        asyncService.asyncMethod();
        System.out.println("主线任务...");
        return "执行异步任务";
    }

    @GetMapping("/async2")
    public String triggerAsync2() {
        // 调用异步方法
        asyncService.asyncMethod2();
        System.out.println("主线任务...");
        return "执行异步任务";
    }

    @GetMapping("/asyncReturn")
    public String triggerAsyncWithReturn() {
        CompletableFuture<String> future = asyncService.asyncMethodWithReturn();

        // 非阻塞的方式处理返回值，使用 thenAccept()、thenApply() 等方法来处理返回值，可以避免阻塞。
        future.thenAccept(result -> {
            System.out.println("接收到结果: " + result);
        });

        // 继续执行其他操作
        System.out.println("主线任务...");
        return "执行有返回值异步任务不阻塞";
    }

    @GetMapping("/asyncReturn2")
    public String triggerAsyncWithReturn2() {
        CompletableFuture<String> future = asyncService.asyncMethodWithReturn();

        // 阻塞直到获取结果
        try {
            String result = future.get(); // 这将会阻塞，直到结果可用
            System.out.println("接收到结果: " + result);
            System.out.println("主线任务...");
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        return "执行有返回值异步任务阻塞";
    }

    @GetMapping("/execute")
    public String execute() {
        // 使用 execute() 执行异步任务，没有返回值。用于提交不需要返回结果的任务。
        primaryExecutor.execute(() -> {
            try {
                // 执行一些操作
                Thread.sleep(2000);
                System.out.println("执行异步任务没有返回值");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        System.out.println("主线任务...");
        return "执行异步任务";
    }

    /**
     * 使用 submit() 提交任务   有返回值    阻塞
     * @return
     */
    @GetMapping("/submit")
    public String submit() {
        // 使用 submit() 提交任务并处理异常，用于提交需要返回结果的任务。
        Future<?> future = primaryExecutor.submit(() -> {
            Thread.sleep(2000);
            System.out.println("使用submit 执行异步任务");
            throw new RuntimeException("任务异常!");
        });

        try {
            // 调用 get() 方法会抛出 ExecutionException  会阻塞
            future.get();
        } catch (InterruptedException | ExecutionException e) {
            System.out.println("抛出异常: " + e.getCause().getMessage());
            // 这里的 e.getCause() 是实际抛出的 RuntimeException
        }
        System.out.println("主线任务...");
        return "执行异步任务";
    }

    /**
     * 使用 CompletableFuture 提交任务   有返回值    阻塞
     * @return
     */
    @GetMapping("/submit2")
    public String submit2() {
        // 使用 CompletableFuture 来处理返回结果，非阻塞
        // 任务完成后的回调处理
        CompletableFuture.supplyAsync(() -> {
            // 模拟耗时操作
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "CompletableFuture处理：返回值.";
        }, primaryExecutor).thenAccept(result -> {
            // 任务完成后的回调处理
            System.out.println("返回值："+result);
        });
        System.out.println("主线任务...");
        return "执行异步任务";
    }


    /**
     * 获取其他线程池
     * @return
     */
    @GetMapping("/other")
    public String other() {
        ThreadPoolTaskExecutor executor = SpringUtil.getBean("testExecutor");
        System.out.println(executor.getCorePoolSize());

        ThreadPoolTaskExecutor executor2 = asyncExecutors.get("testExecutor");
        System.out.println(executor.getMaxPoolSize());
        return "other";
    }


    @GetMapping("/exception")
    public String exception() {
        asyncService.hasException();
        System.out.println("主线任务...");
        return "执行异步任务有异常";
    }

    @GetMapping("/exception2")
    public String exception2() {
        primaryExecutor.execute(() -> {
            throw new RuntimeException("Task exception");
        });
        System.out.println("主线任务...");
        return "执行异步任务有异常";
    }
}
